package com.jochen.core.ui.control

import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.Batch
import com.badlogic.gdx.graphics.g2d.TextureRegion
import com.badlogic.gdx.math.MathUtils
import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.Stage
import com.badlogic.gdx.utils.TimeUtils

open class MenuBackground(private val tiles: List<TextureRegion>) : Actor() {
    
    private var gridHeight = 20
    private var gridWidth: Int = 0
    private var cellSize: Float = 0f
    
    private var aps: FloatArray? = null         
    private var flips: BooleanArray? = null     
    private var apSpeed: FloatArray? = null    
    private var tileIndexes: IntArray? = null   
    
    private val curTiles = mutableListOf<Int>()
    private var createTime: Long = 0

    init {
        setColor(1f, 1f, 1f, 1f)
    }
    
    override fun setStage(stage: Stage?) {
        super.setStage(stage)
        stage?.let { initBackground() }
    }
    
    private fun initBackground() {
        clearAllData()
        cellSize = stage.height / gridHeight
        gridWidth = (stage.width / cellSize).toInt() + 1
        
        val totalCells = gridWidth * gridHeight
        aps = FloatArray(totalCells)          
        flips = BooleanArray(totalCells)    
        apSpeed = FloatArray(totalCells)
        tileIndexes = IntArray(totalCells)
    }
    
    private fun clearAllData() {
        curTiles.clear()
        aps = null
        flips = null
        apSpeed = null
        tileIndexes = null
    }
    
    override fun act(delta: Float) {
        super.act(delta)
        if (TimeUtils.timeSinceMillis(createTime) > 500L) {
            createTime = TimeUtils.millis()
            val (x, y) = randCoord()
            createTile(x, y)
        }
        val removeSet = mutableSetOf<Int>()
        for (index in curTiles) {
            val speed = apSpeed!![index]
            var flip = flips!![index]
            var a = aps!![index]
        
            a = if (flip) a - speed * delta else a + speed * delta
            aps!![index] = MathUtils.clamp(a, 0f, 1.1f)
        
            if (!flip && a >= 1.0f) {
                flips!![index] = true
            } else if (flip && a <= 0) {
                removeSet.add(index)
                aps!![index] = 0f
                flips!![index] = false
                apSpeed!![index] = 0f
                tileIndexes!![index] = 0
            }
        }
        curTiles.removeAll(removeSet)
    }
    
    
    override fun draw(batch: Batch, parentAlpha: Float) {
        val color = color
        val oldAlpha = color.a
        
        for (i in 0 until curTiles.size) {
            val index = curTiles[i]
            val x = index % gridWidth
            val y = index / gridWidth
            
            color.a = oldAlpha * aps!![index]
            batch.color = color
            
            val tile = tiles[tileIndexes!![index]]
            batch.draw(tile, x * cellSize, y * cellSize, cellSize, cellSize)
        }
        
        color.a = oldAlpha
        batch.color = color
    }

    private fun randCoord(): Pair<Int, Int> {
        if (curTiles.size >= gridWidth * gridHeight) return Pair(0, 0)
        
        var x: Int
        var y: Int
        var index: Int
        do {
            x = MathUtils.random(0, gridWidth - 1)
            y = MathUtils.random(0, gridHeight - 1)
            index = y * gridWidth + x
        } while (curTiles.contains(index))
        
        return Pair(x, y)
    }

    
    private fun createTile(x: Int, y: Int) {
        val coord = y * gridWidth + x
        aps!![coord] = 0f
        flips!![coord] = false
        tileIndexes!![coord] = MathUtils.random(0, tiles.size - 1)
        curTiles.add(coord)
        apSpeed!![coord] = MathUtils.random(0.1f, 0.2f)
    }
}